﻿using Leeder.Logger;
using Leeder.Util;
using Leeder.Util.Common;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using ThermalImagery.Business;
using ThermalImagery.Comm;
using ThermalImagery.Hik;
using ThermalImagery.Model;
using System.Threading.Tasks;
using Leeder.Plugin;
using Leeder.Model.Handler;
using System.Diagnostics;

namespace ThermalImagery.Business
{
    public class ThermAlarmBLL
    {
        /// <summary>
        /// 日志
        /// </summary>
        public LogOperate LogObj => Log.GetLogger(this.GetType());

        ThermalCheckBLL thermalCheckBLL = new ThermalCheckBLL();
        PictureBLL pictureBLL = new PictureBLL();
        SetupBLL setupBLL = new SetupBLL();

        /// <summary>
        /// 温度实时检测缓存
        /// </summary>
        private ConcurrentBag<AlarmInfoModel> AlarmInfoBag;
        /// <summary>
        /// 红外检测
        /// </summary>
        ThermAlarm thermAlarm = ThermAlarm.getInstance();
        /// <summary>
        /// IO卡
        /// </summary>
        public IOCardHandler iOCardHandler;

        delegate void OnCheck();//定义委托
        /// <summary>
        /// 温度检测结果通知事件
        /// </summary>
        public event Action<AlarmInfoModel> AlarmEvent;
        /// <summary>
        /// 温度检测开始事件
        /// </summary>
        public event Action<int, string> CheckEvent;
        /// <summary>
        /// 设备状态变化事件
        /// </summary>
        public event Action<bool, string> OnDeviceStateChanged;
        /// <summary>
        /// 检测状态更新事件
        /// </summary>
        public event Action UiUpdateEvent;

        /// <summary>
        /// 当次检测对象ID
        /// </summary>
        long checkDataId = 0;
        /// <summary>
        /// 光眼当前状态
        /// </summary>
        bool PhotoelectricityState = false;
        /// <summary>
        /// 构造函数
        /// </summary>
        public ThermAlarmBLL()
        {
            GolbalVariable.SysSetup = setupBLL.GetModel();
            thermAlarm.DataReceiverEvent += ThermAlarmEvent;
        }

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="RealPlayWnd"></param>
        /// <returns></returns>
        public string Init(PictureBox RealPlayWnd)
        {
            GolbalVariable.NoticInfoBag = new ConcurrentBag<NoticInfoModel>();
            GolbalVariable.AlarmInfoQueue = new ConcurrentQueue<AlarmInfoModel>();
            string errMess = "";
            errMess = "";
            //初始化IO卡
            LoadIOCard(GolbalVariable.SysSetup.PortName);
            iOCardHandler.Start();
            iOCardHandler.OnConnectionBreak += OnConnectionIoCarBreak;
            OnDeviceStateChanged(true, "IO卡");
            //if (!LoadIOCommand(ref errMess))
            //{
            //    return errMess;
            //}
            //热敏相机初始化
            if (!thermAlarm.Init(ref errMess))
            {
                return errMess;
            }
            errMess = "";
            //相机登录
            if (!thermAlarm.Login(GolbalVariable.SysSetup.CameraIP, GolbalVariable.SysSetup.CameraPort.ToString(), GolbalVariable.SysSetup.CameraUserId, GolbalVariable.SysSetup.CameraPwd, ref errMess))
            {
                //登录失败再次登录
                if (!thermAlarm.Login(GolbalVariable.SysSetup.CameraIP, GolbalVariable.SysSetup.CameraPort.ToString(), GolbalVariable.SysSetup.CameraUserId, GolbalVariable.SysSetup.CameraPwd, ref errMess))
                {
                    return errMess;
                }
            }
            errMess = "";
            //开启相机图像实时预览
            if (!thermAlarm.LiveView(RealPlayWnd, ref errMess))
            {
                return errMess;
            }
            OnDeviceStateChanged(true, "红外相机");
            thermAlarm.OnConnectionBreak += OnConnectionHikBreak;
            return "";
        }

        private void LoadIOCard(string comm)
        {
            //IO卡连接和初始化
            iOCardHandler = new IOCardHandler(comm);
            //var ioConfigs = ioCarConfigBLL.GetModelAll();

            var model = new IOCardCMDModel
            {
                ID = 1,//主键
                Code ="001",//指令代码
                Desc = ""//描述
            };
            iOCardHandler.LoadCommand(new List<IOCardCMDModel> { model });
            iOCardHandler.OnInputSignalChanged += OnInputSignalChanged;
            //iOCardHandler.OnOutSignalFail += IOCardHandler_OnOutSignalFail;
            iOCardHandler.IsInitiativeRequest = true;
        }
        Thread thread;
        private void OnInputSignalChanged(List<IOCardSignalModel> list)
        {
            foreach (var item in list)
            {
                //光眼触发
                if ((item.Num == (GolbalVariable.SysSetup.PhotoelectricityInput - 1)) && item.State)
                {
                    thread = new Thread(PhotoelectricityCheckThread);
                    thread.Start();
                    PhotoelectricityState = item.State;
                }
                else if (item.Num == (GolbalVariable.SysSetup.PhotoelectricityInput - 1))
                {
                    if (PhotoelectricityDelayTime >= (GolbalVariable.SysSetup.PhotoelectricityDelay * 5))
                    {
                        UiUpdateEvent?.BeginInvoke(null, null);
                    }
                    PhotoelectricityState = item.State;
                }
                //按钮触发
                if ((item.Num == (GolbalVariable.SysSetup.SwitchInput - 1)) && item.State)
                {
                    StartCheck(2);
                }
            }
        }

        int PhotoelectricityDelayTime = 0;
        private void PhotoelectricityCheckThread()
        {
            PhotoelectricityDelayTime = 0;
            while (PhotoelectricityState)
            {
                PhotoelectricityDelayTime += 1;
                if (PhotoelectricityDelayTime >= (GolbalVariable.SysSetup.PhotoelectricityDelay * 5))
                {
                StartCheck(1);
                    return;
                }
                Thread.Sleep(200);
            }
        }

        private void OnConnectionHikBreak(string str)
        {
            OnDeviceStateChanged(false, "红外相机");
        }

        private void OnConnectionIoCarBreak(string str)
        {
            OnDeviceStateChanged(false, "IO卡");
        }

        /// <summary>
        /// 温度数据接收事件
        /// </summary>
        /// <param name="model">温度检测对象</param>
        private void ThermAlarmEvent(AlarmInfoModel model)
        {
            ThermAlarmCache(model, GolbalVariable.SysSetup.DetectionMode);
        }
        /// <summary>
        /// 温度实时检测数据缓存
        /// </summary>
        /// <param name="model">温度检测对象</param>
        /// <param name="checkType">检测类型，1:温度定值判断，2:温度差值判断(1号区域温度为参考值)</param>
        private void ThermAlarmCache(AlarmInfoModel model, int checkType)
        {
            if (checkType == 1)
            {
                var aib = AlarmInfoBag.Where(p => p.Region == model.Region).FirstOrDefault();
                if (aib == null)
                {
                    AlarmEvent(model);
                    AlarmInfoBag.Add(model);
                }
                else if (model.fCurrTemperature > aib.fCurrTemperature)
                {
                    AlarmEvent(model);
                    aib.fCurrTemperature = model.fCurrTemperature;
                    aib.PictureName = model.PictureName;
                    aib.FilePath = model.FilePath;
                    aib.FileName = model.FileName;
                    aib.Byt = model.Byt;
                    aib.ILen = model.ILen;
                }
            }
            else if (checkType == 2)
            {
                var aib = AlarmInfoBag.Where(p => p.Region == model.Region).FirstOrDefault();
                if (aib == null)
                {
                    AlarmEvent(model);
                    AlarmInfoBag.Add(model);
                }
                else if (model.Region != "1" && model.fCurrTemperature > aib.fCurrTemperature)
                {
                    AlarmEvent(model);
                    aib.fCurrTemperature = model.fCurrTemperature;
                    aib.PictureName = model.PictureName;
                    aib.FilePath = model.FilePath;
                    aib.FileName = model.FileName;
                    aib.Byt = model.Byt;
                    aib.ILen = model.ILen;
                }
            }
        }

        /// <summary>
        /// 开始检测
        /// </summary>
        /// <param name="tirggerType">触发方式：1光眼触发，2硬件按钮触发，3软件按钮触发</param>
        public void StartCheck(int tirggerType)
        {
            //当检测状态中再次触发检测直接返回不作处理
            if (GolbalVariable.IsChecking)
                return;
            //重置当次检测缓存
            CheckEvent(1, "");
            AlarmInfoBag = new ConcurrentBag<AlarmInfoModel>();
            GolbalVariable.IsChecking = true;
            string errMess = "";
            if (!thermAlarm.SetAlarm(ref errMess))
            {
                LogObj.Error("温度检测失败，失败原因：" + errMess);
                return;
            }
            ThermalCheckModel checkModel = new ThermalCheckModel
            {
                CheckTime = DateTime.Now,
                CheckResult = "检测中..",
            };
            checkModel = thermalCheckBLL.Add(checkModel).ActivedObj;
            checkDataId = checkModel.ID;
            /*
            OnCheck ct = new OnCheck(Checking);//实例化委托
            //异步调用
            ct.BeginInvoke((IAsyncResult ar) =>
            {
                Thread.Sleep(50);
                List<PictureModel> list = new List<PictureModel>();
                if(GolbalVariable.SysSetup.DetectionMode == 1)
                {
                    //OK判定逻辑1(固定温度检测)
                    foreach (AlarmInfoModel model in AlarmInfoBag)
                    {
                        list.Add(new PictureModel
                        {
                            ThermalCheckId = checkModel.ID,
                            PictureName = model.PictureName,
                            FCurrTemperature = model.fCurrTemperature.ToString("0.0"), //保留一位小数
                            IsRegionOK = (short)(model.fCurrTemperature >= float.Parse(GolbalVariable.SysSetup.OkValue.ToString()) ? 1 : 0),
                            Region = model.Region
                        });
                        //保存图片
                        string strPath = ".\\picture\\" + model.FilePath + "\\";
                        DirFileHelper.CreateDirectory(strPath);
                        FileStream fs = new FileStream(strPath + model.FileName, FileMode.Create);
                        fs.Write(model.Byt, 0, model.ILen);
                        fs.Close();
                    }
                }
                else if(GolbalVariable.SysSetup.DetectionMode == 2)
                {
                    //OK判定逻辑1(温差检测)
                    var referenceModel = AlarmInfoBag.Where(x => x.Region == "1").FirstOrDefault();
                    foreach (AlarmInfoModel model in AlarmInfoBag)
                    {
                        list.Add(new PictureModel
                        {
                            ThermalCheckId = checkModel.ID,
                            PictureName = model.PictureName,
                            FCurrTemperature = model.fCurrTemperature.ToString("0.0"), //保留一位小数
                            IsRegionOK = (short)(model.fCurrTemperature >= (referenceModel.fCurrTemperature + float.Parse(GolbalVariable.SysSetup.OkDifferenceValue.ToString())) ? 1 : 0),
                            Region = model.Region
                        });
                        //保存图片
                        string strPath = ".\\picture\\" + model.FilePath + "\\";
                        DirFileHelper.CreateDirectory(strPath);
                        FileStream fs = new FileStream(strPath + model.FileName, FileMode.Create);
                        fs.Write(model.Byt, 0, model.ILen);
                        fs.Close();
                    }
                }

                if (list.Where(p => p.IsRegionOK == 1).Count() >= GolbalVariable.SysSetup.OkCount)
                {
                    checkModel.CheckResult = "OK";
                }
                else
                {
                    checkModel.CheckResult = "NG";
                }
                CheckEvent(2, checkModel.CheckResult);
                checkModel.Value = list.Where(p => p.IsRegionOK == 1).Count().ToString();
                thermalCheckBLL.Update(checkModel);

                pictureBLL.AddList(list);
                if(!PhotoelectricityState)
                {
                    //触发UI重置计时
                    var t = System.Threading.Tasks.Task.Run(async delegate
                    {
                        await System.Threading.Tasks.Task.Delay(6000);
                        UiUpdateEvent?.BeginInvoke(null, null);
                    });
                }
            }, null);
            */

            System.Threading.Tasks.Task.Run(async delegate
            {
                await System.Threading.Tasks.Task.Delay(GolbalVariable.SysSetup.CheckTime * 1000);
                GolbalVariable.IsChecking = false;
                if (!thermAlarm.CloseAlarm())
                {
                    LogObj.Error("温度检测结束失败");
                    return;
                }
                Thread.Sleep(50);
                List<PictureModel> list = new List<PictureModel>();
                if (GolbalVariable.SysSetup.DetectionMode == 1)
                {
                    //OK判定逻辑1(固定温度检测)
                    foreach (AlarmInfoModel model in AlarmInfoBag)
                    {
                        list.Add(new PictureModel
                        {
                            ThermalCheckId = checkModel.ID,
                            PictureName = model.PictureName,
                            FCurrTemperature = model.fCurrTemperature.ToString("0.0"), //保留一位小数
                            IsRegionOK = (short)(model.fCurrTemperature >= float.Parse(GolbalVariable.SysSetup.OkValue.ToString()) ? 1 : 0),
                            Region = model.Region
                        });
                        //保存图片
                        string strPath = ".\\picture\\" + model.FilePath + "\\";
                        DirFileHelper.CreateDirectory(strPath);
                        FileStream fs = new FileStream(strPath + model.FileName, FileMode.Create);
                        fs.Write(model.Byt, 0, model.ILen);
                        fs.Close();
                    }
                }
                else if (GolbalVariable.SysSetup.DetectionMode == 2)
                {
                    //OK判定逻辑1(温差检测)
                    var referenceModel = AlarmInfoBag.Where(x => x.Region == "1").FirstOrDefault();
                    foreach (AlarmInfoModel model in AlarmInfoBag)
                    {
                        list.Add(new PictureModel
                        {
                            ThermalCheckId = checkModel.ID,
                            PictureName = model.PictureName,
                            FCurrTemperature = model.fCurrTemperature.ToString("0.0"), //保留一位小数
                            IsRegionOK = (short)(model.fCurrTemperature >= (referenceModel.fCurrTemperature + float.Parse(GolbalVariable.SysSetup.OkDifferenceValue.ToString())) ? 1 : 0),
                            Region = model.Region
                        });
                        //保存图片
                        string strPath = ".\\picture\\" + model.FilePath + "\\";
                        DirFileHelper.CreateDirectory(strPath);
                        FileStream fs = new FileStream(strPath + model.FileName, FileMode.Create);
                        fs.Write(model.Byt, 0, model.ILen);
                        fs.Close();
                    }
                }

                if (list.Where(p => p.IsRegionOK == 1).Count() >= GolbalVariable.SysSetup.OkCount)
                {
                    checkModel.CheckResult = "OK";
                }
                else
                {
                    checkModel.CheckResult = "NG";
                }
                CheckEvent(2, checkModel.CheckResult);
                checkModel.Value = list.Where(p => p.IsRegionOK == 1).Count().ToString();
                thermalCheckBLL.Update(checkModel);

                pictureBLL.AddList(list);
                if (!PhotoelectricityState)
                {
                    //触发UI重置计时
                    //System.Threading.Tasks.Task.Run(async delegate
                    //{
                        await System.Threading.Tasks.Task.Delay(6000);
                        UiUpdateEvent?.BeginInvoke(null, null);
                    //});
                }
            });
        }

        /// <summary>
        /// 检测时间
        /// </summary>
        public void Checking()
        {
            Thread.Sleep(GolbalVariable.SysSetup.CheckTime * 1000);
            GolbalVariable.IsChecking = false;
            if (!thermAlarm.CloseAlarm())
            {
                LogObj.Error("温度检测结束失败");
                return;
            }
        }

        public void Close()
        {
            try { thermAlarm.StopListen(); } catch (Exception ex) { } //停止相机监听
            try { thermAlarm.CloseAlarm(); } catch (Exception ex) { } //关闭相机布防
            try { thermAlarm.StopLiveView(); } catch (Exception ex) { } //关闭相机预览
            try { thermAlarm.Logout(); } catch (Exception ex) { } //注销相机
            //try { IOReadThread.Abort(); Thread.Sleep(200); } catch (Exception ex) { } //停止IO卡状态轮询线程                    
            //try { DataProcessThread.Abort(); Thread.Sleep(200); } catch (Exception ex) { }                  
            try { iOCardHandler.Stop(); } catch (Exception ex) { } //断开IO卡连接
        }
    }
}
